/**
  @(#)$Id: AL_TreeNodeList.h 85 2013-10-17 11:37:59Z xiaoting $
  @brief	Each of the data structure corresponds to a data node storage unit, this storage unit is called storage node, the node can 
  also be referred to.

  The related concepts of tree node 
  1.degree		degree node: A node of the subtree containing the number is called the node degree;
  2.leaf			leaf nodes or terminal nodes: degree 0 are called leaf nodes;
  3.branch		non-terminal node or branch node: node degree is not 0;
  4.parent		parent node or the parent node: If a node contains a child node, this node is called its child node's parent;
  5.child			child node or child node: A node subtree containing the root node is called the node's children;
  6.slibing		sibling nodes: nodes with the same parent node is called mutual sibling;
  7.ancestor		ancestor node: from the root to the node through all the nodes on the branch;
  8.descendant	descendant nodes: a node in the subtree rooted at any node is called the node's descendants.

  ////////////////////////////////Chain storage structure//////////////////////////////////////////
  The computer using a set of arbitrary linear table storage unit stores data elements (which may be a continuous plurality of memory 
  cells, it can be discontinuous).

  It does not require the logic elements of adjacent physical location is adjacent to and therefore it is not sequential storage 
  structure has a weakness, but also lost the sequence table can be accessed randomly advantages.

  Chain store structural features:
  1, compared with sequential storage density storage structure (each node consists of data fields and pointers domains, so the same 
  space is full, then assume full order of more than chain stores).
  2, the logic is not required on the adjacent node is physically adjacent.
  3, insert, delete and flexible (not the mobile node, change the node as long as the pointer).
  4, find the node when stored sequentially slower than the chain stores.
  5, each node is a pointer to the data fields and domains.

  @Author $Author: xiaoting $
  @Date $Date: 2013-10-17 19:37:59 +0800 (周四, 17 十月 2013) $
  @Revision $Revision: 85 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeList.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeList.h 85 2013-10-17 11:37:59Z xiaoting $
 */

#ifndef CXX_AL_TREENODELIST_H
#define CXX_AL_TREENODELIST_H

#ifndef CXX_AL_LISTSINGLE_H
#include "AL_ListSingle.h"
#endif

#ifndef CXX_AL_QUEUELIST_H
#include "AL_QueueList.h"
#endif

///////////////////////////////////////////////////////////////////////////
//			AL_TreeNodeList
///////////////////////////////////////////////////////////////////////////

template<typename T> class AL_TreeList;


template<typename T> 
class AL_TreeNodeList
{
friend class AL_TreeList<T>;

public:
	/**
	* Destruction
	*
	* @param
	* @return
	* @note
	* @attention 
	*/
	~AL_TreeNodeList();
	
	/**
	* GetLevel
	*
	* @param
	* @return	DWORD
	* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
	* @attention 
	*/
	DWORD GetLevel() const;

	/**
	* SetLevel
	*
	* @param	DWORD dwLevel <IN>
	* @return	
	* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
	* @attention 
	*/
	VOID SetLevel(DWORD dwLevel);

	/**
	* GetData
	*
	* @param
	* @return	T
	* @note 
	* @attention 
	*/
	T GetData() const;

	/**
	* SetData
	*
	* @param	const T& tData <IN>
	* @return	
	* @note 
	* @attention 
	*/
	VOID SetData(const T& tData);

	/**
	* GetParent
	*
	* @param	
	* @return	AL_TreeNodeList<T>*	
	* @note parent node pointer, not to manager memory
	* @attention 
	*/
	AL_TreeNodeList<T>*	GetParent() const;

	/**
	* SetParent
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeList<T>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the index (from the left of parent's child )
	*/
	BOOL SetParent(DWORD dwIndex, AL_TreeNodeList<T>* pParent);

	/**
	* SetParentLeft
	*
	* @param	AL_TreeNodeList<T>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the left (from the left of parent's child )
	*/
	BOOL SetParentLeft(AL_TreeNodeList<T>* pParent);

	/**
	* SetParentRight
	*
	* @param	AL_TreeNodeList<T>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the right (from the right of parent's child )
	*/
	BOOL SetParentRight(AL_TreeNodeList<T>* pParent);

	/**
	* Insert
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeList<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeList<T>*  into the child notes at the position
	* @attention
	*/
	BOOL Insert(DWORD dwIndex, AL_TreeNodeList<T>* pInsertChild);

	/**
	* InsertLeft
	*
	* @param	AL_TreeNodeList<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeList<T>*  into the child notes at the left
	* @attention
	*/
	BOOL InsertLeft(AL_TreeNodeList<T>* pInsertChild);

	/**
	* InsertRight
	*
	* @param	AL_TreeNodeList<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeList<T>*  into the child notes at the right
	* @attention
	*/
	BOOL InsertRight(AL_TreeNodeList<T>* pInsertChild);
	
	/**
	* RemoveParent
	*
	* @param
	* @return	BOOL
	* @note remove the parent note
	* @attention
	*/
	BOOL RemoveParent();

	/**
	* Remove
	*
	* @param	AL_TreeNodeList<T>* pRemoveChild <IN>
	* @return	BOOL
	* @note remove the notes in the child
	* @attention
	*/
	BOOL Remove(AL_TreeNodeList<T>* pRemoveChild);

	/**
	* Remove
	*
	* @param	DWORD dwIndex <IN>
	* @return	BOOL
	* @note remove the child notes at the position
	* @attention
	*/
	BOOL Remove(DWORD dwIndex);

	/**
	* RemoveLeft
	*
	* @param
	* @return	BOOL
	* @note remove the child notes at the left
	* @attention
	*/
	BOOL RemoveLeft();

	/**
	* RemoveRight
	*
	* @param
	* @return	BOOL
	* @note remove the child notes at the right
	* @attention
	*/
	BOOL RemoveRight();

	/**
	* GetChild
	*
	* @param	DWORD dwIndex <IN>
	* @return	AL_TreeNodeList<T>*
	* @note the dwIndex must is little than the node degree
	* @attention
	*/
	AL_TreeNodeList<T>* GetChild(DWORD dwIndex) const;

	/**
	* GetChildLeft
	*
	* @param	
	* @return	AL_TreeNodeList<T>*
	* @note 
	* @attention
	*/
	AL_TreeNodeList<T>* GetChildLeft() const;

	/**
	* GetChildRight
	*
	* @param	
	* @return	AL_TreeNodeList<T>*
	* @note 
	* @attention
	*/
	AL_TreeNodeList<T>* GetChildRight() const;
	
	/**
	* GetDegree
	*
	* @param
	* @return	DWORD
	* @note degree node: A node of the subtree containing the number is called the node degree;
	* @attention 
	*/
	DWORD GetDegree() const;

	/**
	* IsLeaf
	*
	* @param
	* @return	BOOL
	* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
	* @attention 
	*/
	BOOL IsLeaf() const;

	/**
	* IsBranch
	*
	* @param
	* @return	BOOL
	* @note non-terminal node or branch node: node degree is not 0;
	* @attention 
	*/
	BOOL IsBranch() const;

	/**
	* IsParent
	*
	* @param	const AL_TreeNodeList<T>* pChild <IN>
	* @return	BOOL
	* @note parent node or the parent node: If a node contains a child node, this node is called its child 
	* @attention 
	*/
	BOOL IsParent(const AL_TreeNodeList<T>* pChild) const;

	/**
	* GetSibling
	*
	* @param	AL_ListSingle<AL_TreeNodeList<T>*>& listSibling <OUT>
	* @return	BOOL
	* @note sibling nodes: nodes with the same parent node is called mutual sibling;
	* @attention 
	*/
	BOOL GetSibling(AL_ListSingle<AL_TreeNodeList<T>*>& listSibling) const;

	/**
	* GetAncestor
	*
	* @param	AL_ListSingle<AL_TreeNodeList<T>*>& listAncestor <OUT>
	* @return	BOOL
	* @note ancestor node: from the root to the node through all the nodes on the branch;
	* @attention 
	*/
	BOOL GetAncestor(AL_ListSingle<AL_TreeNodeList<T>*>& listAncestor) const;

	/**
	* GetDescendant
	*
	* @param	AL_ListSingle<AL_TreeNodeList<T>*>& listDescendant <OUT>
	* @return	BOOL
	* @note ancestor node: from the root to the node through all the nodes on the branch;
	* @attention 
	*/
	BOOL GetDescendant(AL_ListSingle<AL_TreeNodeList<T>*>& listDescendant) const;

	/**
	* Clear
	*
	* @param
	* @return	VOID
	* @note
	* @attention 
	*/
	VOID Clear();

protected:
private:

	/**
	* Construction
	*
	* @param
	* @return
	* @note private the Construction, avoid the others use it
	* @attention
	*/
	AL_TreeNodeList();
	
	/**
	* Construction
	*
	* @param	const T& tData <IN>
	* @return
	* @note
	* @attention private the Construction, avoid the others use it
	*/
	AL_TreeNodeList(const T& tData);

	/**
	*Copy Construct
	*
	* @param	const AL_TreeNodeList<T>& cAL_TreeNodeList
	* @return
	*/
	AL_TreeNodeList(const AL_TreeNodeList<T>& cAL_TreeNodeList);

	/**
	*Assignment
	*
	* @param	const AL_TreeNodeList<T>& cAL_TreeNodeList
	* @return	AL_TreeNodeList<T>&
	*/
	AL_TreeNodeList<T>& operator = (const AL_TreeNodeList<T>& cAL_TreeNodeList);

public:
protected:
private:
	DWORD								m_dwLevel;				//Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
	T									m_tData;					//the friend class can use it directly

	AL_TreeNodeList<T>*						m_pParent;				//Parent tree node
	AL_ListSingle<AL_TreeNodeList<T>*>		m_listChild;			//All Child tree node
};

///////////////////////////////////////////////////////////////////////////
//			AL_TreeNodeList
///////////////////////////////////////////////////////////////////////////

/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template<typename T>
AL_TreeNodeList<T>::AL_TreeNodeList():
m_dwLevel(0x00),
m_pParent(NULL)
{
	//memset(&m_tData, 0x00, sizeof(T));		//can not use memset, as to pointer or virtural pointer of class
	m_listChild.Clear();
}

/**
* Construction
*
* @param	const T& tData <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template<typename T>
AL_TreeNodeList<T>::AL_TreeNodeList(const T& tData):
m_dwLevel(0x00),
m_tData(tData),
m_pParent(NULL)
{
	m_listChild.Clear();
}


/**
* Destruction
*
* @param
* @return
* @note
* @attention 
*/
template<typename T>
AL_TreeNodeList<T>::~AL_TreeNodeList()
{
	//it doesn't matter to clear the pointer or not.
	Clear();
}

/**
* GetLevel
*
* @param
* @return	DWORD
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
* @attention 
*/
template<typename T> DWORD 
AL_TreeNodeList<T>::GetLevel() const
{
	return m_dwLevel;
}

/**
* SetLevel
*
* @param	DWORD dwLevel <IN>
* @return	
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeList<T>::SetLevel(DWORD dwLevel)
{
	m_dwLevel = dwLevel;
}

/**
* GetData
*
* @param
* @return	T
* @note 
* @attention 
*/
template<typename T> T 
AL_TreeNodeList<T>::GetData() const
{
	return m_tData;
}

/**
* SetData
*
* @param	const T& tData <IN>
* @return	
* @note 
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeList<T>::SetData(const T& tData)
{
	m_tData = tData;
}

/**
* GetParent
*
* @param	
* @return	AL_TreeNodeList<T>*	
* @note parent node pointer, not to manager memory
* @attention 
*/
template<typename T> AL_TreeNodeList<T>* 
AL_TreeNodeList<T>::GetParent() const
{
	return m_pParent;
}

/**
* SetParent
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeList<T>* pParent <IN>
* @return	BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the index (from the left of parent's child )
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::SetParent(DWORD dwIndex, AL_TreeNodeList<T>* pParent)
{
	if (NULL == pParent) {
		return FALSE;
	}

	BOOL  bSetParent = FALSE;
	bSetParent = pParent->Insert(dwIndex, this);
	if (TRUE == bSetParent) {
		//current node insert to the parent successfully
		if (NULL != m_pParent) {
			//current node has parent
			if (FALSE == m_pParent->Remove(this)) {
				return FALSE;
			}
		}
		m_pParent = pParent;
	}
	return bSetParent;
}

/**
* SetParentLeft
*
* @param	AL_TreeNodeList<T>* pParent <IN>
* @return	
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the left (from the left of parent's child )
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::SetParentLeft(AL_TreeNodeList<T>* pParent)
{
	return SetParent(0x00, pParent);
}

/**
* SetParentRight
*
* @param	AL_TreeNodeList<T>* pParent <IN>
* @return	
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the right (from the right of parent's child )
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::SetParentRight(AL_TreeNodeList<T>* pParent)
{
	if (NULL == pParent) {
		return FALSE;
	}

	return SetParent(pParent->GetDegree(), pParent);
}

/**
* Insert
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeList<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeList<T>*  into the child notes at the position
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::Insert(DWORD dwIndex, AL_TreeNodeList<T>* pInsertChild)
{
	if (GetDegree() < dwIndex || NULL == pInsertChild) {
		return FALSE;
	}

	if (this == pInsertChild) {
		//itself
		return FALSE;
	}

	BOOL  bInsert = FALSE;
	bInsert = m_listChild.Insert(dwIndex, pInsertChild);
	if (TRUE == bInsert) {
		if (GetLevel()+1 != pInsertChild->GetLevel()) {
			//deal with the child level
			INT iLevelDiff = pInsertChild->GetLevel() - GetLevel();
			pInsertChild->SetLevel(GetLevel()+1);

			AL_ListSingle<AL_TreeNodeList<T>*> listDescendant;
			AL_TreeNodeList<T>* pDescendant = NULL;
			if (TRUE == GetDescendant(listDescendant)) {
				//insert child node has descendant
				for (DWORD dwCnt=0x00; dwCnt<listDescendant.Length(); dwCnt++) {
					if (TRUE == listDescendant.Get(dwCnt, pDescendant)) {
						if (NULL != pDescendant) {
							//set child level
							pDescendant->SetLevel(pDescendant->GetLevel()-iLevelDiff+1);
						}
						else {
							//error
							return FALSE;
						}
					}
					else {
						//error
						return FALSE;
					}
				}
			}
		}
		//child node insert to the current successfully
		pInsertChild->m_pParent = this;
	}
	return bInsert;
}

/**
* InsertLeft
*
* @param	AL_TreeNodeList<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeList<T>*  into the child notes at the left
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::InsertLeft(AL_TreeNodeList<T>* pInsertChild)
{
	return Insert(0x00, pInsertChild);
}

/**
* InsertRight
*
* @param	AL_TreeNodeList<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeList<T>*  into the child notes at the right
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::InsertRight(AL_TreeNodeList<T>* pInsertChild)
{
	return Insert(GetDegree(), pInsertChild);
}

/**
* RemoveParent
*
* @param
* @return	BOOL
* @note remove the parent note
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::RemoveParent()
{
	BOOL bRemove = FALSE;
	//don't care the parent node exist or not
	m_pParent = NULL;
	bRemove = TRUE;
	/*
	if (NULL != m_pParent) {
		m_pParent = NULL;
		bRemove = TRUE;
	}
	*/
	return bRemove;
}

/**
* Remove
*
* @param	AL_TreeNodeList<T>* pRemoveChild <IN>
* @return	BOOL
* @note remove the notes in the child
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::Remove(AL_TreeNodeList<T>* pRemoveChild)
{
	return m_listChild.Remove(pRemoveChild);
}

/**
* Remove
*
* @param	DWORD dwIndex <IN>
* @return	BOOL
* @note remove the child notes at the position
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::Remove(DWORD dwIndex)
{
	AL_TreeNodeList<T>* pRemoveChild = NULL;
	if (FALSE == m_listChild.Get(pRemoveChild, dwIndex)) {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* RemoveLeft
*
* @param
* @return	BOOL
* @note remove the child notes at the left
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::RemoveLeft()
{
	AL_TreeNodeList<T>* pRemoveChild = NULL;
	if (FALSE == m_listChild.Get(pRemoveChild, 0x00)) {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* RemoveRight
*
* @param
* @return	BOOL
* @note remove the child notes at the right
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::RemoveRight()
{
	AL_TreeNodeList<T>* pRemoveChild = NULL;
	if (FALSE == m_listChild.Get(pRemoveChild, GetDegree())) {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* GetChild
*
* @param	DWORD dwIndex <IN>
* @return	AL_TreeNodeList<T>*
* @note the dwIndex must is little than the node degree
* @attention
*/
template<typename T> AL_TreeNodeList<T>* 
AL_TreeNodeList<T>::GetChild(DWORD dwIndex) const
{
	AL_TreeNodeList<T>* pChild = NULL;
	if (TRUE == m_listChild.Get(dwIndex, pChild)) {
		return pChild;
	}
	return NULL;
}

/**
* GetChildLeft
*
* @param	
* @return	AL_TreeNodeList<T>*
* @note 
* @attention
*/
template<typename T> AL_TreeNodeList<T>* 
AL_TreeNodeList<T>::GetChildLeft() const
{
	return GetChild(0x00);
}

/**
* GetChildRight
*
* @param	
* @return	AL_TreeNodeList<T>*
* @note 
* @attention
*/
template<typename T> AL_TreeNodeList<T>* 
AL_TreeNodeList<T>::GetChildRight() const
{
	return GetChild(GetDegree());
}

/**
* GetDegree
*
* @param
* @return	DWORD
* @note degree node: A node of the subtree containing the number is called the node degree;
* @attention 
*/
template<typename T> DWORD 
AL_TreeNodeList<T>::GetDegree() const
{
	return m_listChild.Length();
}

/**
* IsLeaf
*
* @param
* @return	BOOL
* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::IsLeaf() const
{
//	return (TRUE == m_listChild.IsEmpty()) ? TRUE:FALSE;
	return (0x00 == GetDegree()) ? TRUE:FALSE;
}

/**
* IsBranch
*
* @param
* @return	BOOL
* @note non-terminal node or branch node: node degree is not 0;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::IsBranch() const
{
//	return (FALSE == m_listChild.IsEmpty()) ? TRUE:FALSE;
	return (0x00 != GetDegree()) ? TRUE:FALSE;
}

/**
* IsParent
*
* @param	const AL_TreeNodeList<T>* pChild <IN>
* @return	BOOL
* @note parent node or the parent node: If a node contains a child node, this node is called its child 
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::IsParent(const AL_TreeNodeList<T>* pChild) const
{
	if (NULL ==  pChild) {
		return FALSE;
	}
// 	AL_TreeNodeList<T>* pCompare = NULL;
// 	for (DWORD dwCnt=0x00; dwCnt<GetDegree(); dwCnt++) {
// 		if (TRUE == m_listChild.Get(pCompare, dwCnt)) {
// 			if (pCompare == pChild) {
// 				//find the child
// 				return TRUE;
// 			}
// 		}
// 	}
// 	return FALSE;

	if (this == pChild->m_pParent) {
		return TRUE;
	}
	return FALSE;
}

/**
* GetSibling
*
* @param	AL_ListSingle<AL_TreeNodeList<T>*>& listSibling <OUT>
* @return	BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention 
*/
template<typename T> BOOL
AL_TreeNodeList<T>::GetSibling(AL_ListSingle<AL_TreeNodeList<T>*>& listSibling) const
{
	BOOL bSibling = FALSE;
	if (NULL == m_pParent) {
		//not parent node
		return bSibling;
	}
	
	listSibling.Clear();
	AL_TreeNodeList<T>* pParentChild = NULL;
	for (DWORD dwCnt=0x00; dwCnt<m_pParent->GetDegree(); dwCnt++) {
		pParentChild = m_pParent->GetChild(dwCnt);
		if (NULL != pParentChild) {
			//get the child
			if (pParentChild == this) {
				//itself
				continue;
			}
			listSibling.InsertEnd(pParentChild);
			bSibling = TRUE;
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}
	return bSibling;
}

/**
* GetAncestor
*
* @param	AL_ListSingle<AL_TreeNodeList<T>*>& listAncestor <OUT>
* @return	BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention 
*/
template<typename T> BOOL
AL_TreeNodeList<T>::GetAncestor(AL_ListSingle<AL_TreeNodeList<T>*>& listAncestor) const
{
	if (NULL == m_pParent) {
		//not parent node
		return FALSE;
	}
	
	listAncestor.Clear();
	AL_TreeNodeList<T>* pParent = m_pParent;
	while (NULL != pParent) {
		listAncestor.InsertEnd(pParent);
		pParent = pParent->m_pParent;
	}
	return TRUE;
}

/**
* GetDescendant
*
* @param	AL_ListSingle<AL_TreeNodeList<T>*>& listDescendant <OUT>
* @return	BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeList<T>::GetDescendant(AL_ListSingle<AL_TreeNodeList<T>*>& listDescendant) const
{
	if (TRUE == IsLeaf()) {
		//child node
		return FALSE;
	}
	
	listDescendant.Clear();
	AL_TreeNodeList<T>* pDescendant = NULL;
	for (DWORD dwCnt=0x00; dwCnt<GetDegree(); dwCnt++) {
		pDescendant = GetChild(dwCnt);
		if (NULL != pDescendant) {
			//get the child
			listDescendant.InsertEnd(pDescendant);
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}

	//loop the all node in listDescendant
	DWORD dwDescendantLoop = 0x00;
	AL_TreeNodeList<T>* pDescendantLoop = NULL;
	while (TRUE == listDescendant.Get(dwDescendantLoop, pDescendant)) {
		dwDescendantLoop++;
		if (NULL != pDescendant) {
			for (DWORD dwCnt=0x00; dwCnt<pDescendant->GetDegree(); dwCnt++) {
				pDescendantLoop = pDescendant->GetChild(dwCnt);
				if (NULL != pDescendantLoop) {
					//get the descendant
					listDescendant.InsertEnd(pDescendantLoop);
				}
				else {
					//error can not get the descendant
					return FALSE;
				}
			}
		}
		else {
			//error
			return FALSE;
		}
	}
	return TRUE;
	/*
	AL_TreeNodeList<T>* pDescendant = NULL;
	AL_QueueList<AL_TreeNodeList<T>*> queueDescendant;
	for (DWORD dwCnt=0x00; dwCnt<GetDegree(); dwCnt++) {
		pDescendant = GetChild(dwCnt);
		if (NULL != pDescendant) {
			//get the child
			queueDescendant.Push(pDescendant);
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}
	AL_TreeNodeList<T>* pDescendantLoop = NULL;
	AL_TreeNodeList<T>* pDescendantChild = NULL;
	while (FALSE == queueDescendant.IsEmpty()) {
		if (TRUE == queueDescendant.Pop(pDescendantLoop)) {
			if (NULL != pDescendantLoop) {
				listDescendant.InsertEnd(pDescendantLoop); 
				for (DWORD dwCnt=0x00; dwCnt<pDescendantLoop->GetDegree(); dwCnt++) {
					pDescendantChild = pDescendantLoop->GetChild(dwCnt);
					if (NULL != pDescendantChild) {
						queueDescendant.Push(pDescendantChild);
					}
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}
	return TRUE;
	*/
}

/**
* Clear
*
* @param
* @return	VOID
* @note
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeList<T>::Clear()
{
	m_dwLevel = 0x00;
	m_pParent = NULL;		//not to manager the memory
	m_listChild.Clear();
}

/**
*Assignment
*
* @param	const AL_TreeNodeList<T>& cAL_TreeNodeList
* @return	AL_TreeNodeList<T>&
*/
template<typename T> AL_TreeNodeList<T>& 
AL_TreeNodeList<T>::operator = (const AL_TreeNodeList<T>& cAL_TreeNodeList)
{
	m_dwLevel = cAL_TreeNodeList.m_dwLevel;
	m_tData = cAL_TreeNodeList.m_tData;
	m_pParent = cAL_TreeNodeList.m_pParent;
	m_listChild = cAL_TreeNodeList.m_listChild;
	return *this;
}
#endif // CXX_AL_TREENODELIST_H
/* EOF */
